using MongoDB.Driver;
using System.Linq.Expressions;

namespace Beauty.Net.MongoDB.Core;

/// <summary>
/// MongoDB服务接口
/// </summary>
public interface IMongoDBService
{
    /// <summary>
    /// 获取数据库
    /// </summary>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>MongoDB数据库</returns>
    IMongoDatabase GetDatabase(string? databaseName = null);

    /// <summary>
    /// 获取集合
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>MongoDB集合</returns>
    IMongoCollection<T> GetCollection<T>(string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 插入单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="document">文档</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    void InsertOne<T>(T document, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步插入单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="document">文档</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>任务</returns>
    Task InsertOneAsync<T>(T document, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 插入多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="documents">文档集合</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    void InsertMany<T>(IEnumerable<T> documents, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步插入多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="documents">文档集合</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>任务</returns>
    Task InsertManyAsync<T>(IEnumerable<T> documents, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 查询单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档</returns>
    T? FindOne<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步查询单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档</returns>
    Task<T?> FindOneAsync<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 查询文档集合
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档集合</returns>
    List<T> FindMany<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步查询文档集合
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档集合</returns>
    Task<List<T>> FindManyAsync<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 更新单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="update">更新操作</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>更新结果</returns>
    UpdateResult UpdateOne<T>(Expression<Func<T, bool>> filter, UpdateDefinition<T> update, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步更新单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="update">更新操作</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>更新结果</returns>
    Task<UpdateResult> UpdateOneAsync<T>(Expression<Func<T, bool>> filter, UpdateDefinition<T> update, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 更新多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="update">更新操作</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>更新结果</returns>
    UpdateResult UpdateMany<T>(Expression<Func<T, bool>> filter, UpdateDefinition<T> update, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步更新多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="update">更新操作</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>更新结果</returns>
    Task<UpdateResult> UpdateManyAsync<T>(Expression<Func<T, bool>> filter, UpdateDefinition<T> update, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 删除单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>删除结果</returns>
    DeleteResult DeleteOne<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步删除单个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>删除结果</returns>
    Task<DeleteResult> DeleteOneAsync<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 删除多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>删除结果</returns>
    DeleteResult DeleteMany<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步删除多个文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>删除结果</returns>
    Task<DeleteResult> DeleteManyAsync<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 替换文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="replacement">替换文档</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>替换结果</returns>
    ReplaceOneResult ReplaceOne<T>(Expression<Func<T, bool>> filter, T replacement, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步替换文档
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="replacement">替换文档</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>替换结果</returns>
    Task<ReplaceOneResult> ReplaceOneAsync<T>(Expression<Func<T, bool>> filter, T replacement, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 统计文档数量
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档数量</returns>
    long Count<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);

    /// <summary>
    /// 异步统计文档数量
    /// </summary>
    /// <typeparam name="T">文档类型</typeparam>
    /// <param name="filter">过滤条件</param>
    /// <param name="collectionName">集合名称，不指定则使用类型名称</param>
    /// <param name="databaseName">数据库名称，不指定则使用配置中的数据库名称</param>
    /// <returns>文档数量</returns>
    Task<long> CountAsync<T>(Expression<Func<T, bool>> filter, string? collectionName = null, string? databaseName = null);
}